
# -*- encoding: utf-8 -*-
"""
@Project : AIGateWay 
@FileName: async_handler
@Time    : 2020/11/26 14:59
@Author  : chenych
@Desc    :
"""

from Client.asyn_request import AsynClient
from Core import  SYS_CODE
import json
import ailog
import time
from util.check_resp_util import RespException,asyn_check_resp
from Core import conf
from util.image_util import image_pos,image_area,base64toarray
import datetime

class StrangeRecogTask():
    host = conf.get('face_ability_url', 'host_face')
    port = conf.get('face_ability_url', 'port_face')
    url_image = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url', 'url_image'))
    url_index_search_base = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url', 'url_index_search_base'))
    url_index_create = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url', 'url_index_create'))
    url_face_create_base = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url', 'url_face_create_base'))
    url_face_search = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url', 'url_face_search'))

    scoreThreshold = 70.0
    score = 0

    area_score = 3600
    area_pos_score = 0.3
    area_drop = 0.2

    face_quality_score = 60

    FACE_QUALITY = 1
    FACE_MORE = 2
    FACE_POS = 3
    FACE_AREA = 4
    NO_FACE = 5
    FACE_NO_MATCH = 6

    FACE_MSG_DICT = {
        FACE_QUALITY: '人脸质量评分低',
        FACE_MORE: '检测多个人脸',
        FACE_POS: '人脸位置不合格',
        FACE_AREA: '人脸大小不合格',
        NO_FACE: '未检测到人脸',
        FACE_NO_MATCH: '没有符合条件的人脸'

    }


    asynClient = AsynClient()

    @staticmethod
    def __build_resp(seqid, code, message, flag, data):

        resp_dict = {

            'seqid': seqid,
            'code': code,
            'message': message,
            'flag': flag,
            'data': data
        }

        return resp_dict

    @classmethod
    async def __get_featrue(cls, imageBase64s):

        data = {
            'objectType': 'FACE',
            'imageBase64s': imageBase64s,
            'maxObjectAllowed': 3,
            'extractType': 'DEFAULT',
            'option': {}
        }
        header = {'Content-type': 'application/json'}

        res_feature = await cls.asynClient.post(url=cls.url_image, body=json.dumps(data), header=header)

        res_feature = json.loads(res_feature)
        return res_feature

    @classmethod
    async def __search_index(cls,deviceId):


        url_index_search = cls.url_index_search_base.format(deviceId)
        header = {'Content-type': 'application/json'}

        res_index_search = await cls.asynClient.get(url=url_index_search, body=json.dumps({}), header=header)

        res_index_search = json.loads(res_index_search)
        ailog.debug(res_index_search)
        return res_index_search

    @classmethod
    async def __create_index(cls, deviceId):

        data = {
            'indexName': deviceId,
            'indexType': 'FACE',
            'indexStoreType': 'FLAT'
        }
        header = {'Content-type': 'application/json'}

        res_index_create = await cls.asynClient.post(url=cls.url_index_create, body=json.dumps(data), header=header)

        res_index_create = json.loads(res_index_create)
        ailog.debug(res_index_create)
        return res_index_create

    @classmethod
    async def __create_face(cls, deviceId, visitorId, featureType, featureData, version):

        data = [{
            'featureId': visitorId,
            'featureType': featureType,
            'featureData': featureData,
            'version': version,
        }]

        url_face_create = cls.url_face_create_base.format(deviceId)

        header = {'Content-type': 'application/json'}

        res_face_create = await cls.asynClient.post(url=url_face_create, body=json.dumps(data), header=header)

        res_face_create = json.loads(res_face_create)

        return res_face_create

    @classmethod
    async def __search_face(cls, indexNames, featureType, featureData, version, scoreThreshold):
        data = {
            'indexNames': [indexNames],
            'feature': {
                'featureType': featureType,
                'featureData': featureData,
                'version': version,
                'bitSet': '',
                'criteria': [],
            },
            'scoreThreshold': scoreThreshold,
            'limit': 1,
            'readPreference': "PRIMARY"

        }
        header = {'Content-type': 'application/json'}

        res = await cls.asynClient.post(url=cls.url_face_search, body=json.dumps(data), header=header)
        res = json.loads(res)
        return res

    @classmethod
    def check_face_result(cls,imageBase64s,feature):

        position = feature['position']

        faceQuality  =feature['faceQuality']

        img_array = base64toarray(imageBase64s)

        all_h, all_w, _ = img_array.shape
        #all_h = 360
        #all_w = 640

        # if faceQuality<cls.face_quality_score:
        #
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_QUALITY,'')
        #     return False,msg+str(faceQuality)

        # if image_area(position['width'],position['height'])<cls.FACE_AREA:
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_AREA, '')
        #     return False, msg+str(image_area(position['width'],position['height']))

        # pos_score =  image_pos(fea_x1=position['left'],fea_y1=(all_h-position['top']),fea_h=position['height'],fea_w=position['width'],
        #              all_w=all_w,all_h=all_h,drop=cls.area_drop)
        # if pos_score<cls.area_pos_score:
        #
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_POS, '')
        #     return False, msg+str(pos_score)

        return True,'检测通过'

    @classmethod
    async def run(cls, seqid, deviceId, visitorId, imageBase64s_list):


        start_time =time.time()



        try:
            print(len(imageBase64s_list))
            #查库
            res_search_index = await cls.__search_index(deviceId=deviceId)
            print("res_search_index",res_search_index)
            INDEX_EXIT =True  if res_search_index['code'] ==0 else False
            ailog.info('Index is exit : {}'.format(INDEX_EXIT))



            #获取特征
            #多个图片抽特征
            feature_list = []
			
            #获取特征			
			res_feature = await cls.__get_featrue(imageBase64s)

            for f in res_feature['data']:
				
                #获取特征
                feature_list += f['data']['objects']
                  
    


            for feature_dict in feature_list:

                feature = feature_dict['feature']

                res_search_face = await cls.__search_face(indexNames=deviceId,
                                                          featureType=feature['featureType'],
                                                          featureData=feature['featureData'],
                                                          version=feature['version'],
                                                          scoreThreshold=cls.scoreThreshold)
                print(res_search_face)
                if res_search_face['data']['total'] >= 1:
                    face_data = res_search_face['data']['features'][0]

                    # 匹配上人脸
                    if face_data['score'] > cls.score:
                        visitorId = face_data['featureId']


                        data = {
                            'visitorId': visitorId,
                            'timeSecond': time.time() - start_time
                        }

                        resp_dict = cls.__build_resp(seqid=seqid,
                                                     code=SYS_CODE.RESPCODE.SUCCESS,
                                                     message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.SUCCESS),
                                                     flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                                     data=data)

                        return resp_dict





            #判断没有人脸
            if len(feature_list)==0:

                data = {
                    'visitorId': '',
                    'timeSecond': time.time() - start_time
                }
                resp_dict = cls.__build_resp(seqid=seqid,
                                             code=SYS_CODE.STATUS.SUCCESS,
                                             message=cls.FACE_MSG_DICT.get(cls.NO_FACE,''),
                                             flag=SYS_CODE.RESPCODE.FLAG_FAIL,
                                             data=data)

                return resp_dict




            #==============未匹配到================
            ailog.info('FACE NOT MATCH...')


            for imageBase64s,res_f in zip(imageBase64s_list,feature_list):

                feature = res_f['feature']


                orgin_feature_list_copy = feature_list
                feature_list = []
                for f_dict in orgin_feature_list_copy:
                    FEATURE_CHECK,CHECK_MSG = cls.check_face_result(imageBase64s,f_dict)
                    #符合条件
                    if FEATURE_CHECK:
                        feature_list.append(f_dict)

                #####符合入库 条件


                # 没有符合人脸
                if len(feature_list) == 0:
                    data = {
                        'visitorId': '',
                        'timeSecond': time.time() - start_time
                    }
                    continue



                #多个人脸未匹配上
                if len(feature_list) >1:

                    data = {
                        'visitorId': '',
                        'timeSecond': time.time() - start_time
                    }
                    ailog.info('{} : {}'.format('多个人脸未匹配上', res_feature))
                    continue


                #单人脸未匹配
                if len(feature_list)==1:


                    ailog.info('{} : {}'.format('单人脸未匹配', res_feature))

                    feature_dict = feature_list[0]

                    FEATURE_CHECK,CHECK_MSG = cls.check_face_result(imageBase64s,feature_dict)

                    #未合格
                    if not FEATURE_CHECK:

                        data = {
                            'visitorId': '',
                            'timeSecond': time.time() - start_time
                        }

                        ailog.info('{} : {}'.format(FEATURE_CHECK,CHECK_MSG))

                        continue


                    #合格
                    else:

                        #没库
                        if not INDEX_EXIT:

                            ailog.info('创建库。')


                            res_create_index = await cls.__create_index(deviceId=deviceId)
                            res_create_face = await cls.__create_face(deviceId=deviceId,
                                                                      visitorId=visitorId,
                                                                      featureType=feature['featureType'],
                                                                      featureData=feature['featureData'],
                                                                      version=feature['version'])

                        
                            
                        #有库
                        else:

                            ailog.info('创建档案。')

                            await cls.__create_face(deviceId=deviceId,
                                                               visitorId=visitorId,
                                                               featureType=feature['featureType'],
                                                               featureData=feature['featureData'],
                                                               version=feature['version'])




                        data = {
                            'visitorId': visitorId,
                            'timeSecond': time.time() - start_time
                        }

                        resp_dict = cls.__build_resp(seqid=seqid,
                                                     code=SYS_CODE.RESPCODE.SUCCESS,
                                                     message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.SUCCESS),
                                                     flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                                     data=data)

                        return resp_dict



            data = {
                'visitorId':'',
                'timeSecond':time.time()-start_time
            }
            ailog.info('NOT MATCH RULE')

            resp_dict = cls.__build_resp(seqid=seqid,
                                         code=SYS_CODE.RESPCODE.FAIL,
                                         message='NOT MATCH RULE',
                                         flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                         data=data)

            return resp_dict



        except Exception as e:

            ailog.error('error : {}'.format(e))

            resp_dict = cls.__build_resp(seqid=seqid,
                                         code=SYS_CODE.RESPCODE.FAIL,
                                         message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.FAIL),
                                         flag=SYS_CODE.RESPCODE.FLAG_FAIL,
                                         data={})

            return resp_dict































